from semantic import *
from Eparser.feature import *
from sql import SemanticSQL 
import sys

sem = SemanticRuleSet()
identity = lambda x: x

### Rules ###

# Start rules
sem.add("Start -> S", lambda s: processSentence(s))
sem.add("Start -> If S Then S", lambda i, s1, t, s2: ifthenSentence(s1, s2))
sem.add("Start -> Q[wh +]", lambda q: whQuestion(q))
sem.add("Start -> Q[wh -]", lambda q: ynQuestion(q))
sem.add("Start -> HQ[hw +]", lambda q: hwQuestion(q))
sem.add("Start -> LocQ[wh +]", lambda q: locQuestion(q))
sem.add("Start -> InsQ[wh +]", lambda q: insQuestion(q))

# Declarative sentence
sem.add("S -> NP[wh -] VP", lambda np, vp: vp(np))

# Yes-no question
sem.add("Q[wh -] -> Do_Modal[not -] NP[wh -] AV VBAR[fin +] AVPP/AV",
	lambda dm, np, av, vbar, avpp: dm(avpp(av(vbar(np)))))
sem.add("Q[wh -] -> Do_Modal[not -] NP[wh -] VBAR[fin +] AVPP",
	lambda dm, np, vbar, avpp: dm(avpp(vbar(np))))
sem.add("Q[wh -] -> Do_Modal[not -] NP[wh -] VBAR[fin +]",
	lambda dm, np, vbar: dm(vbar(np)))
sem.add("Q[wh -] -> Do_Modal/Not NP[wh -] Not[not +] AV VBAR[fin +] AVPP/AV",
	lambda dm, np, ntp, av, vbar, avpp: dm(ntp(avpp(av(vbar(np))))))
sem.add("Q[wh -] -> Do_Modal/Not NP[wh -] Not[not +] VBAR[fin +] AVPP",
	lambda dm, np, ntp, vbar, avpp: dm(avpp(ntp(vbar(np)))))
sem.add("Q[wh -] -> Do_Modal/Not NP[wh -] Not[not +] VBAR[fin +]",
	lambda dm, np, ntp, vbar: dm(ntp(vbar(np))))
# Yes-No Be questions
sem.add("Q[wh -] -> VBE[tense +] NP[wh -] Not[not ?nt] AVPPBE",
	lambda vbe, np, ntp, avpp: avpp(ntp(vbe(np, StarCategory()))))
sem.add("Q[wh -] -> VBE[tense +] NP[wh -] Not[not ?nt] NP[wh -] AVPPBE",
	lambda vbe, np, ntp, nps, avpp: avpp(ntp(vbe(np, nps))))
sem.add("Q[wh -] -> VBE[tense +] NP[wh -] Not[not ?nt] NP[wh -]",
	lambda vbe, np, ntp, nps: ntp(vbe(np, nps)))
sem.add("Q[wh -] -> Be[tense +] NP[wh -] Not[not ?nt] V.part[form V2] AVPPBE",
	lambda be, np, ntp, vpart, avppbe: be(avppbe(ntp(vpart(StarCategory(),np)))))
sem.add("Q[wh -] -> Be[tense +] NP[wh -] Not[not ?nt] V.part[form V2]",
	lambda be, np, ntp, vpart: be(ntp(vpart(StarCategory(), np))))
sem.add("Q[wh -] -> Be[tense +] NP[wh -] Not[not ?nt] V.part[form V2] PP.by",
	lambda be, np, ntp, vpart, pp: be(ntp(vpart(pp, np))))
sem.add("Q[wh -] -> Be[tense +] NP[wh -] Not[not ?nt] V.part[form V3]",
	lambda be, np, ntp, vpart: be(ntp(vpart(StarCategory(), StarCategory(), np))))
sem.add("Q[wh -] -> Be[tense +] NP[wh -] Not[not ?nt] V.part[form V3] PP.by",
	lambda be, np, ntp, vpart, pp: be(ntp(vpart(pp, StarCategory(), np))))
sem.add("Q[wh -] -> Be[tense +] NP[wh -] Not[not ?nt] V.part[form V3] PP.dat",
	lambda be, np, ntp, vpart, pp: be(ntp(vpart(StarCategory(), pp, np))))
sem.add("Q[wh -] -> Be[tense +] NP[wh -] Not[not ?nt] V.part[form V3] PP.dat PP.by",
	lambda be, np, ntp, vpart, pp, ppb: be(ntp(vpart(ppb, pp, np))))
sem.add("Q[wh -] -> Be[tense +] NP[wh -] Not[not ?nt] V.part[form V3] PP.by PP.dat",
	lambda be, np, ntp, vpart, pp, ppd: be(ntp(vpart(pp, ppd, np))))
sem.add("Q[wh -] -> VBE[tense +] NP[wh -] Not[not ?nt] APBE",
	lambda vbe, np, ntp, apbe: ntp(apbe(vbe(np, StarCategory()))))

# How did....
sem.add("HQ[hw +] -> AVP[hw +] Do_Modal[not -] NP[wh -] VBAR[fin +] AVPP/AV",
	lambda avp, dm, np, vbar, avpp: dm(avpp(vbar(np))))
sem.add("HQ[hw +] -> AVP[hw +] Do_Modal[not -] NP[wh -] VBAR[fin +]",
	lambda avp, dm, np, vbar: dm(avp(vbar(np))))
sem.add("HQ[hw +] -> AVP[hw +] Do_Modal/Not NP[wh -] Not[not +] VBAR[fin +] AVPP/AV",
	lambda avp, dm, np, ntp, vbar, avpp: dm(ntp(avpp(vbar(np)))))
sem.add("HQ[hw +] -> AVP[hw +] Do_Modal/Not NP[wh -] Not[not +] VBAR[fin +]",
	lambda avp, dm, np, ntp, vbar: dm(ntp(avp(vbar(np)))))

# Where did ...
sem.add("LocQ[wh +] -> LOC[q +] Do_Modal[not -] NP[wh -] VBAR[fin +] AVPP/LOC",
	lambda loc, dm, np, vbar, avpp: dm(avpp(vbar(np))))
sem.add("LocQ[wh +] -> LOC[q +] Do_Modal[not -] NP[wh -] AVPP/LOC VBAR[fin +]",
	lambda loc, dm, np, avpp, vbar: dm(avpp(vbar(np))))
sem.add("LocQ[wh +] -> LOC[q +] Do_Modal[not -] NP[wh -] VBAR[fin +]",
	lambda loc, dm, np, vbar: dm(loc(vbar(np))))
sem.add("LocQ[wh +] -> LOC[q +] Do_Modal/Not NP[wh -] Not[not +] VBAR[fin +] AVPP/LOC",
	lambda loc, dm, np, ntp, vbar, avpp: dm(ntp(avpp(vbar(np)))))
sem.add("LocQ[wh +] -> LOC[q +] Do_Modal/Not NP[wh -] Not[not +] AVPP/LOC VBAR[fin +]",
	lambda loc, dm, np, ntp, avpp, vbar: dm(ntp(avpp(vbar(np)))))
sem.add("LocQ[wh +] -> LOC[q +] Do_Modal/Not NP[wh -] Not[not +] VBAR[fin +]",
	lambda loc, dm, np, ntp, vbar: dm(ntp(loc(vbar(np)))))
# Where was ...
sem.add("LocQ[wh +] -> LOC[q +] VBE[tense +] NP[wh -] Not[not ?nt]",
	lambda loc, vbe, np, ntp: ntp(loc(vbe(np, StarCategory()))))
sem.add("LocQ[wh +] -> LOC[q +] VBE[tense +] NP[wh -] Not[not ?nt] NP[wh -]",
	lambda loc, vbe, np, ntp, nps: ntp(loc(vbe(np, nps))))
sem.add("LocQ[wh +] -> LOC[q +] Be[tense +] NP[wh -] Not[not ?nt] V.part[form V2]",
	lambda loc, be, np, ntp, vpart: ntp(loc(be(vpart(StarCategory(),np)))))
sem.add("LocQ[wh +] -> LOC[q +] Be[tense +] NP[wh -] Not[not ?nt] V.part[form V2] PP.by",
	lambda loc, be, np, ntp, vpart, pp: ntp(loc(be(vpart(pp,np)))))
sem.add("LocQ[wh +] -> LOC[q +] Be[tense +] NP[wh -] Not[not ?nt] V.part[form V3] PP.by",
	lambda loc, be, np, ntp, vpart, pp: ntp(loc(be(vpart(pp, StarCategory(), np)))))
sem.add("LocQ[wh +] -> LOC[q +] Be[tense +] NP[wh -] Not[not ?nt] V.part[form V3] PP.dat",
	lambda loc, be, np, ntp, vpart, pp: ntp(loc(be(vpart(StarCategory(), pp, np)))))
sem.add("LocQ[wh +] -> LOC[q +] Be[tense +] NP[wh -] Not[not ?nt] V.part[form V3] PP.dat PP.by",
	lambda loc, be, np, ntp, vpart, pp, ppb: ntp(loc(be(vpart(ppb, pp, np)))))
sem.add("LocQ[wh +] -> LOC[q +] Be[tense +] NP[wh -] Not[not ?nt] V.part[form V3] PP.by PP.dat",
	lambda loc, be, np, ntp, vpart, pp, ppd: ntp(loc(be(vpart(pp, ppd, np)))))
	
	
# What did...with
sem.add("InsQ[wh +] -> INS[q +] Do_Modal[not -] NP[wh -] VBAR[fin +] AVPP/IP With",
	lambda ins, dm, np, vbar, avpp, w: dm(avpp(vbar(np))))
sem.add("InsQ[wh +] -> INS[q +] Do_Modal[not -] NP[wh -] AVPP/IP VBAR[fin +] With",
	lambda ins, dm, np, avpp, vbar, w: dm(avpp(vbar(np))))
sem.add("InsQ[wh +] -> INS[q +] Do_Modal[not -] NP[wh -] VBAR[fin +] With",
	lambda ins, dm, np, vbar, w: dm(ins(vbar(np))))
sem.add("InsQ[wh +] -> INS[q +] Do_Modal/Not NP[wh -] Not[not +] VBAR[fin +] AVPP/IP With",
	lambda ins, dm, np, ntp, vbar, avpp, w: dm(ntp(avpp(vbar(np)))))
sem.add("InsQ[wh +] -> INS[q +] Do_Modal/Not NP[wh -] Not[not +] AVPP/IP VBAR[fin +] With",
	lambda ins, dm, np, ntp, avpp, vbar, w: dm(ntp(avpp(vbar(np)))))
sem.add("InsQ[wh +] -> INS[q +] Do_Modal/Not NP[wh -] Not[not +] VBAR[fin +] With",
	lambda ins, dm, np, ntp, vbar, w: dm(ntp(ins(vbar(np)))))

# Who/What
sem.add("Q[wh +] -> NP[wh +] VP", 
	lambda np, vp: vp(np))
sem.add("Q[wh +] -> NP[wh +] Q/NP",
	lambda np, q: q(np))

sem.add("Q/NP -> Do_Modal[not -] NP VBAR[fin +]/NP AVPP",
	lambda dm, np, vbar, avpp: lambda object: dm(avpp(vbar(np, object))))
sem.add("Q/NP -> Do_Modal[not -] NP AV VBAR[fin +]/NP AVPP/AV",
	lambda dm, np, av, vbar, avpp: lambda object: dm(avpp(av(vbar(np, object)))))
sem.add("Q/NP -> Do_Modal[not -] NP VBAR[fin +]/NP",
	lambda dm, np, vbar: lambda object: dm(vbar(np, object)))
sem.add("Q/NP -> Do_Modal/Not NP Not[not +] VBAR[fin +]/NP AVPP",
	lambda dm, np, ntp, vbar, avpp: lambda object: dm(ntp(avpp(vbar(np, object)))))
sem.add("Q/NP -> Do_Modal/Not NP Not[not +] AV VBAR[fin +]/NP AVPP/AV",
	lambda dm, np, ntp, av, vbar, avpp: lambda object: dm(ntp(avpp(av(vbar(np, object))))))
sem.add("Q/NP -> Do_Modal/Not NP Not[not +] VBAR[fin +]/NP",
	lambda dm, np, ntp, vbar: lambda object: dm(ntp(vbar(np, object))))
#Who is...
sem.add("Q/NP -> Be[tense +] NP[wh -] Not[not ?nt] V.part[form V2] PP.by/NP",
	lambda be, np, ntp, vpart, ppnp: lambda object: be(ntp(vpart(object, np))))
sem.add("Q/NP -> Be[tense +] NP[wh -] Not[not ?nt] V.part[form V3] PP.by/NP",
	lambda be, np, ntp, vpart, ppnp: lambda object: be(ntp(vpart(object, StarCategory(), np))))
#sem.add("Q[wh -] -> Be[tense +] NP[wh -] Not[not ?nt] V.part[form V3] PP.by PP.dat",
#	lambda be, np, ntp, vpart, pp, ppd: be(ntp(vpart(pp, ppd, np))))

sem.add("VBAR[fin +]/NP -> V2[tense -] NP/NP",
	lambda v2, e: v2)

sem.add("VBAR[fin +]/NP -> V3[tense -] NP PP.dat/NP",
	lambda v3, np, pp: lambda subj, beneficiary: v3(subj, beneficiary, np))

sem.add("VBAR[fin +]/NP -> V3[tense -] NP/NP PP.dat",
	lambda v3, np, pp: lambda subj, patient: v3(subj, pp, patient))

# NP
sem.add("NP[pro -, wh -] -> Name", identity)
sem.add("NP[pro -, wh -] -> Det AP* N", lambda det, apstar, n: n(det, apstar))
sem.add("NP[pro -, wh -] -> AP* N", lambda apstar, n: n('all', apstar))
sem.add("NP[pro -, wh -] -> AP* N[mass +]", lambda apstar, nmass: nmass(False, apstar))
sem.add("NP[pro -, wh -] -> Det[mass +] AP* N[mass +]", lambda det, apstar, nmass: nmass(det,apstar))
sem.add("NP[pro -, wh -] -> QuantP AP* N", lambda quant, apstar, n: n(quant, apstar))
sem.add("NP[pro -, wh -] -> Everyone", identity)

# AP
sem.add("AP* -> AP* A", lambda apstar, ap: C(ap, mod=apstar))
sem.add("AP* ->", lambda: StarCategory())
sem.add("APBE -> A", lambda ap: lambda subj: subj.addFeature("adjective",ap))
#sem.add("AP -> A", identity)

# Adverbs
sem.addMatch("AV -> *", lambda av: lambda vp: vp.addFeature("adverb",av))
sem.addMatch("AVP[hw +] -> *", lambda word: lambda vp: vp.addFeature("adverb",VariableValue(word)))
sem.addLexicon("AVP[hw +]", ['how'])

# Location
sem.add("LOC[by +] -> P[loc +, by +] NP[wh -]", lambda p, np: lambda vp: vp.addFeature("location", C(None, loc_prep=p, loc_target=np)))
sem.add("LOC[by -] -> P[loc +, by -] NP[wh -]", lambda p, np: lambda vp: vp.addFeature("location", C(None, loc_prep=p, loc_target=np)))
sem.addMatch("LOC[q +] -> *", lambda word: lambda vp: vp.addFeature("location",VariableValue(word)))
sem.addLexicon("LOC[q +]", ['where'])

# Instrument Phrase
sem.add("IP -> With NP[wh -]", lambda w, np: lambda vp: vp.addFeature("instrument",np))
sem.add("INS[q +] -> NP[wh +]", lambda np: lambda vp: vp.addFeature("instrument",np))
#sem.addMatch("INS[q +] -> *", lambda word: lambda vp: vp.addFeature("instrument",VariableValue(word)))
#sem.addLexicon("INS[q +]", ['what, who'])

# AVPP
sem.add("AVPPBE[by ?x] -> AV LOC[by ?x] IP", lambda av, loc, ip: lambda vp: ip(loc(av(vp))))
sem.add("AVPPBE[by ?x] -> AV IP LOC[by ?x]", lambda av, ip, loc: lambda vp: loc(ip(av(vp))))
sem.add("AVPPBE[by ?x] -> AV LOC[by ?x]", lambda av, loc: lambda vp: loc(av(vp)))
sem.add("AVPPBE -> AV IP", lambda av, ip: lambda vp: ip(av(vp)))

sem.add("AVPPBE[by ?x] -> LOC[by ?x] IP", lambda loc, ip: lambda vp: ip(loc(vp)))
sem.add("AVPPBE[by ?x] -> IP LOC[by ?x]", lambda ip, loc: lambda vp: loc(ip(vp)))
sem.add("AVPPBE[by ?x] -> LOC[by ?x]", lambda loc: lambda vp: loc(vp))
sem.add("AVPPBE -> IP", lambda ip: lambda vp: ip(vp))

sem.add("AVPPBE/AV[by ?x] -> LOC[by ?x] IP", lambda loc, ip: lambda vp: ip(loc(vp)))
sem.add("AVPPBE/AV[by ?x] -> IP LOC[by ?x]", lambda ip, loc: lambda vp: loc(ip(vp)))
sem.add("AVPPBE/AV[by ?x] -> LOC[by ?x]", lambda loc: lambda vp: loc(vp))
sem.add("AVPPBE/AV -> IP", lambda ip: lambda vp: ip(vp))

sem.add("AVPP[by ?x] -> AV LOC[by ?x] IP", lambda av, loc, ip: lambda vp: ip(loc(av(vp))))
sem.add("AVPP[by ?x] -> AV IP LOC[by ?x]", lambda av, ip, loc: lambda vp: loc(ip(av(vp))))
sem.add("AVPP[by ?x] -> AV LOC[by ?x]", lambda av, loc: lambda vp: loc(av(vp)))
sem.add("AVPP -> AV IP", lambda av, ip: lambda vp: ip(av(vp)))
sem.add("AVPP -> AV", lambda av: lambda vp: av(vp))

sem.add("AVPP[by ?x] -> LOC[by ?x] IP", lambda loc, ip: lambda vp: ip(loc(vp)))
sem.add("AVPP[by ?x] -> IP LOC[by ?x]", lambda ip, loc: lambda vp: loc(ip(vp)))
sem.add("AVPP[by ?x] -> LOC[by ?x]", lambda loc: lambda vp: loc(vp))
sem.add("AVPP -> IP", lambda ip: lambda vp: ip(vp))

sem.add("AVPP/AV[by ?x] -> LOC[by ?x] IP", lambda loc, ip: lambda vp: ip(loc(vp)))
sem.add("AVPP/AV[by ?x] -> IP LOC[by ?x]", lambda ip, loc: lambda vp: loc(ip(vp)))
sem.add("AVPP/AV[by ?x] -> LOC[by ?x]", lambda loc: lambda vp: loc(vp))
sem.add("AVPP/AV -> IP", lambda ip: lambda vp: ip(vp))
sem.add("AVPP/AV -> ", lambda: lambda vp: vp)

sem.add("AVPP/LOC -> AV IP", lambda av, ip: lambda vp: ip(av(vp)))
sem.add("AVPP/LOC -> IP", lambda ip: lambda vp: ip(vp))
sem.add("AVPP/LOC -> AV", lambda av: lambda vp: av(vp))

sem.add("AVPP/IP[by ?x] -> AV LOC[by ?x]", lambda av, loc: lambda vp: loc(av(vp)))
sem.add("AVPP/IP[by ?x] -> LOC[by ?x]", lambda loc: lambda vp: loc(vp))
sem.add("AVPP/IP -> AV", lambda av: lambda vp: av(vp))

# VP
sem.add("VP -> Not[not -] V+args AVPP[by ?x]", lambda ntp, v, avpp: lambda subj: ntp(avpp(v(subj))))
sem.add("VP -> Not[not -] AV V+args AVPP/AV[by ?x]", lambda ntp, av, v, avpp: lambda subj: ntp(avpp(av(v(subj)))))
sem.add("VP -> Not[not -] V+args", lambda ntp, v: lambda subj: ntp(v(subj)))

sem.add("VP -> V+be AVPPBE[by -]", lambda v, avpp: lambda subj: avpp(v(subj)))
sem.add("VP -> AV V+be AVPPBE/AV[by -]", lambda av, v, avpp: lambda subj: avpp(av(v(subj))))
sem.add("VP -> V+be", lambda v: lambda subj: v(subj))

sem.add("VP -> AV Do_Modal[not ?nt] VBAR[fin +] AVPP/AV[by -]", lambda av, dm, vbar, avpp: lambda subj: dm(avpp(av(vbar(subj)))))
sem.add("VP -> Do_Modal[not ?nt] AV VBAR[fin +] AVPP/AV[by -]", lambda av, dm, vbar, avpp: lambda subj: dm(avpp(av(vbar(subj)))))
sem.add("VP -> Do_Modal[not ?nt] VBAR[fin +] AVPP[by -]", lambda dm, vbar, avpp: lambda subj: dm(avpp(vbar(subj))))
sem.add("VP -> Do_Modal[not ?nt] VBAR[fin +]", lambda dm, vbar: lambda subj: dm(vbar(subj)))

sem.add("V+be -> Be[tense +] Not[not ?ntp] V.part[form V2]",
	lambda be, ntp, vpart: lambda subj: ntp(be(vpart(Category.parse("Object"), subj))))
sem.add("V+be -> Be[tense +] Not[not ?ntp] V.part[form V2] PP.by",
	lambda be, ntp, vpart, pp: lambda subj: ntp(be(vpart(pp, subj))))
sem.add("V+be -> Be[tense +] Not[not ?ntp] V.part[form V3] PP.by PP.dat",
	lambda be, ntp, vpart, pp, ppd: lambda subj: ntp(be(vpart(pp, ppd, subj))))
sem.add("V+be -> Be[tense +] Not[not ?ntp] V.part[form V3] PP.dat PP.by",
	lambda be, ntp, vpart, ppd, pp: lambda subj: ntp(be(vpart(pp, ppd, subj))))
sem.add("V+be -> Be[tense +] Not[not ?ntp] V.part[form V3] PP.by",
	lambda be, ntp, vpart, pp: lambda subj: ntp(be(vpart(pp, StarCategory(), subj))))
sem.add("V+be -> Be[tense +] Not[not ?ntp] V.part[form V3] PP.dat",
	lambda be, ntp, vpart, pp: lambda subj: ntp(be(vpart(StarCategory(), pp, subj))))
sem.add("V+be -> VBE[tense +] Not[not ?ntp]",
	lambda be, ntp: lambda subj: ntp(be(subj, StarCategory())))
sem.add("V+be -> VBE[tense +] Not[not ?ntp] NP",
	lambda be, ntp, np: lambda subj: ntp(be(subj, np)))
sem.add("V+be -> VBE[tense +] APBE",
	lambda be, apbe: lambda subj: apbe(be(subj, StarCategory())))

sem.add("V+args -> V1[tense +]", lambda v1: lambda subj: v1(subj))

sem.add("VBAR[fin +] -> V1[tense -]", lambda v1: lambda subj: v1(subj))

sem.add("V+args -> V2[tense +] NP", lambda v2, np: lambda subj: v2(subj, np))

sem.add("VBAR[fin +] -> V2[tense -] NP[wh -]",
	lambda v2, np: lambda subj: v2(subj, np))

sem.add("V+args -> V3[tense +] NP[wh -] PP.dat",
	lambda v3, np, pp: lambda subj: v3(subj, pp, np))
sem.add("VBAR[fin +] -> V3[tense -] NP[wh -] PP.dat",
	lambda v3, np, pp: lambda subj: v3(subj, pp, np))

# VBAR[fin -]
sem.add("VBAR[fin -] -> To VBAR[fin +]",
	lambda to, vbar: lambda subj: vbar(subj))
# Q_emb
sem.add("Q_emb -> SBAR.comp[wh +]", identity)

# AP.pred
sem.add("AP.pred -> A.pred PP", lambda a, ppstar: a(ppstar))

# PP
sem.add("PP[loc ?x] -> P[loc ?x] NP[wh -]", lambda p, np: p(np))
sem.add("PP -> P NP", lambda p, np: p(np))
sem.add("PP.dat -> P.dat NP", lambda p, np: p(np))
sem.add("PP.by -> P.by NP[wh -]", lambda p, np: p(np))
sem.add("PP.by/NP -> P.by", lambda p: p)

# SBAR.that
sem.add("SBAR.that -> That S", lambda that, s: s)

# SBAR.comp[wh +]
sem.add("SBAR.comp[wh +] -> Comp[wh +] S", lambda comp, s: s)

# SBAR.for
sem.add("SBAR.for -> For NP[wh -] VBAR[fin -]",
	lambda for_, np, vbar: vbar(np))

# Do or Modal
sem.add("Do_Modal/Not -> Do[tense +]", identity)
sem.add("Do_Modal/Not -> Modal", identity)
sem.add("Do_Modal[not ?nt] -> Do[tense +] Not[not ?nt]", lambda x, y: lambda z: x(y(z)))
sem.add("Do_MoDal[not ?nt] -> Modal Not[not ?nt]", lambda x, y: lambda z: x(y(z)))

sem.add("Not[not +] -> 'not'", lambda x: lambda z: z.addFeature("negation", 1==1))
sem.add("Not[not -] ->", lambda: lambda z: z.addFeature("negation", 0==1))

# Empty slash rules
sem.add("NP/NP ->", lambda: None)
sem.add("PP.dat/NP -> P.dat NP/NP", lambda p, np: None)



### Lexicon ###
def addVerb(form, root, past, present, ppart=None):
	global sem
	if ppart is None: ppart = past
	(pos, proc) = form
	sem.add(CFGProduction(pos.mix(C(None, tense=False)), root),
		proc(root, False))
	sem.add(CFGProduction(pos.mix(C(None, tense=True)), root),
		proc(root, "present"))
	sem.add(CFGProduction(pos.mix(C(None, tense=True)), past),
		proc(root, "past"))
	sem.add(CFGProduction(pos.mix(C(None, tense=True)), present),
		proc(root, "present"))
	sem.add(CFGProduction(C("V.part", form=pos), ppart),
		proc(root, "past-participle"))
    
v1form = (C("V1"),
    lambda root, tense:\
        lambda word: lambda agent:\
            C("Event", action=root, agent=agent, tense=tense))

v2form = (C("V2"),
    lambda root, tense:\
        lambda word: lambda agent, patient:\
            C("Event", action=root, agent=agent, patient=patient, tense=tense))

v3form = (C("V3"),
    lambda root, tense:\
        lambda word: lambda agent, beneficiary, patient:\
            C("Event", action=root, agent=agent, patient=patient, beneficiary=beneficiary, tense=tense))

vBeform = (C("VBE"),
    lambda root, tense:\
        lambda word: lambda agent, patient:\
            C("Event", action=root, patient=patient,agent=agent, tense=tense))

# Names
sem.addMatch("Name -> *", lambda name:\
	C("Object", name=name))
sem.addMatch("Everyone -> *", lambda word:\
	C("Object", type='person', definite='all'))
sem.addLexicon("Everyone", ['everyone'])
	
# Common nouns
sem.addMatch("N[mass -] -> *", lambda word:\
	lambda det, apstar:\
		C("Object", type=word, definite=det, mod=apstar))

sem.addMatch("N[mass +] -> *", lambda word:\
	lambda det, apstar:\
		C("Object", type=word, definite=det, number='mass',
		mod=apstar))

# Determiners
sem.add("Det -> 'the'", lambda word: True)
sem.add("Det -> 'this'", lambda word: True)
sem.add("Det -> 'a'", lambda word: False)
sem.add("Det -> 'an'", lambda word: False)
sem.add("Det[mass +] -> 'the'", lambda word: True)
sem.add("Det[mass +] -> 'this'", lambda word: True)

# Quantifiers
sem.add("QuantP -> 'all'", lambda word: 'all')
sem.add("QuantP -> 'every'", lambda word: 'all')
sem.add("QuantP -> 'most'", lambda word: 'most')
sem.add("QuantP -> 'some'", lambda word: 'some')
sem.add("QuantP -> 'few'", lambda word: 'some')

# wh-words
sem.addMatch("NP[pro +, wh +] -> *", lambda word: VariableValue(word))
#sem.addMatch("NP[pro +, wh +] -> *", lambda word: "?who")
sem.addLexicon("NP[pro +, wh +]", ['who', 'what'])

# Prepositions
sem.add("P[loc +, by -] -> 'in'", lambda word: C(word))
sem.add("P[loc +, by -] -> 'under'", lambda word: C(word))
sem.add("P[loc +, by -] -> 'on'", lambda word: C(word))
sem.add("P[loc +, by -] -> 'above'", lambda word: C(word))
sem.add("P[loc +, by -] -> 'near'", lambda word: C(word))
sem.add("P[loc +, by -] -> 'around'", lambda word: C(word))
sem.add("P[loc +, by +] -> 'by'", lambda word: C(word))
sem.add("P[loc +, by -] -> 'inside'", lambda word: C(word))
sem.add("P[loc +, by -] -> 'beside'", lambda word: C(word))

sem.add("P[loc -] -> 'of'",
	lambda word: lambda source: lambda frame:\
	frame.addFeature("source", source))

sem.add("P.dat -> 'to'",
	lambda word: identity)

sem.add("P.by -> 'by'",
	lambda word: identity)

# Adjectives
sem.addMatch("A -> *", lambda word: C(word))

sem.add("A.pred -> 'suspicious'", lambda word: lambda source:\
	C("suspicious", source=source))

# Aux and Modal
sem.add("Do[tense +] -> 'did'",
	lambda word: lambda verb_frame:\
	verb_frame.addFeature("tense", "past"))

sem.add("Do[tense +] -> 'does'",
	lambda word: lambda verb_frame:\
	verb_frame.addFeature("tense", "present"))

sem.add("Do[tense +] -> 'do'",
	lambda word: lambda verb_frame:\
	verb_frame.addFeature("tense", "present"))

sem.add("Be[tense +] -> 'is'",
	lambda word: lambda verb_frame:\
	verb_frame.addFeature("tense", "present"))

sem.add("Be[tense +] -> 'was'",
	lambda word: lambda verb_frame:\
	verb_frame.addFeature("tense", "past"))

sem.add("Modal -> 'can'",
	lambda word: lambda verb_frame:\
	verb_frame.addFeature("mood", "can").addFeature("tense", "present"))

sem.add("To -> 'to'", lambda word: lambda: None)
sem.add("That -> 'that'", lambda word: lambda: None)
sem.add("There -> 'there'", lambda word: lambda: None)
sem.add("Then -> 'then'", lambda word: lambda: None)
sem.add("If -> 'if'", lambda word: lambda: None)
sem.add("With -> 'with'", lambda word: lambda: None)
sem.add("Comp[wh +] -> 'whether'", lambda word: lambda: None)
sem.add("NP[wh -, pro +] -> 'somebody'", lambda word: C("Object"))



### Sentence processing ###

sql = None

def initSQL(dbc):
	global sql
	sql = SemanticSQL(dbc)

def loadVocab():
	global sql
	global sem
	cursor = sql.getCursor()
	#Get Verbs
	sqlverbs = "SELECT * FROM `VERB`"
	cursor.execute(sqlverbs)
	result = cursor.fetchall()
	addVerb(vBeform,"be","was","is","been")
	for record in result:
		typenum = record[0]
		tense1 = record[1]
		tense2 = record[2]
		tense3 = record[3]
		tense4 = record[4]
		if typenum == 1:
			addVerb(v1form,tense1,tense2,tense3,tense4)
		if typenum == 2:
			addVerb(v2form,tense1,tense2,tense3,tense4)
		if typenum == 3:
			addVerb(v3form,tense1,tense2,tense3,tense4)
	sqlnouns = "SELECT * FROM `NOUN`"
	cursor.execute(sqlnouns)
	result = cursor.fetchall()
	for record in result:
		nountype = record[0]
		noun = record[1]
		sem.addLexicon(nountype,[noun])
	sqladverbs = "SELECT * FROM `ADVERB`"
	cursor.execute(sqladverbs)
	result = cursor.fetchall()
	for record in result:
		adverb = record[0]
		sem.addLexicon('AV',[adverb])
	sqladjectives = "SELECT * FROM `ADJECTIVE`"
	cursor.execute(sqladjectives)
	result = cursor.fetchall()
	for record in result:
		adjective = record[0]
		sem.addLexicon('A',[adjective])

def processSentence(data):
	return(sql.add(data))
#	return "Okay."

def ifthenSentence(data1, data2):
	print "If-Then Sentence"
	sqlm = sql.match(data1)
	if str(sqlm.getFinalAnswer())=="Yes":
		#htmlUtils.writeLog(sqlm)
		print "If-Then successful."
		sqlm2 = sql.add(data2)
		sqlm2.setFinalAnswer("Cause was found, Effect added to database.")
		return sqlm2
	else:
		sqlm.setFinalAnswer("Cause not found, Effect will not be added.")
		return sqlm

def ynQuestion(data):
	return(sql.match(data))
#	if sql.match(data) is not None: return "Yes."
#	else: return "No."

def whQuestion(data):
	return(sql.matchVar(data))
#	if vars is None: return "I don't know."
#	else:
#		if len(vars.keys()) == 1:
#			return translate(vars.values()[0])
#		else:
#			return translate(sem.learned.match(data))

def hwQuestion(data):
	return(sql.matchAdv(data))

def locQuestion(data):
	return(sql.matchLoc(data))

def insQuestion(data):
	return(sql.matchIns(data))

def translate(data):
	if data.symbol() == "Object":
		name = data.getFeature("name").value()
		definite = data.getFeature("definite").value()
		plural = data.getFeature("plural").value()
		type = data.getFeature("type").value()
		mod = translateModifier(data.getFeature("mod").value())
		desc = "%s%s" % (mod, type)
		if name != Category.null():
			return name
		elif type != Category.null():
			if definite: return "the %s" % desc
			else:
				if plural: return "some %s" % desc
				else: return "a %s" % desc
		else: return "something"
	elif data.symbol() == "Place":
		relation = data.getFeature("relation").value()
		location = translate(data.getFeature("location").value())
		return "%s %s" % (relation, location)
	else: return repr(data)

def translateModifier(data):
	if data == Category.null(): return ""
	else: return "%s%s " %\
	(translateModifier(data.getFeature("mod").value()), data.symbol())

